/*
 *              Copyright (C) 2011 The MusicMod Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *            http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.musicmod.android.activity;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.KeyguardManager;
import android.app.SearchManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.GestureDetector.OnGestureListener;
import android.view.View.OnTouchListener;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;

import org.musicmod.android.Constants;
import org.musicmod.android.IMusicPlaybackService;
import org.musicmod.android.R;
import org.musicmod.android.utils.*;
import org.musicmod.android.utils.VisualizerWrapper.OnDataCaptureListener;
import org.musicmod.android.view.*;
import org.musicmod.android.widget.TextScrollView;
import org.musicmod.android.widget.RepeatingImageButton;
import org.musicmod.android.widget.TextScrollView.OnLineSelectedListener;

public class MusicPlaybackActivity extends Activity implements Constants,
		OnTouchListener, OnLineSelectedListener {

	private boolean mSeeking = false;
	private boolean mDeviceHasDpad = false;
	private long mStartSeekPos = 0;
	private long mLastSeekEventTime;
	private IMusicPlaybackService mService = null;
	private RepeatingImageButton mPrevButton, mNextButton;
	private ImageButton mPauseButton, mRepeatButton, mShuffleButton,
			mQueueButton;
	private Toast mToast;
	private ServiceToken mToken;
	private boolean mIntentDeRegistered = false;
	private boolean mVisualizerAntialias = false;
	private int mVisualizerType;
	private int mVisualizerRefreshRate = 12;
	private int mVisualizerAccuracy = 48;
	private int mUIColor;
	private boolean mAutoColor = true;
	private boolean mBlurBackground = false;

	GestureDetector mGestureDetector;
	private View mVolumeSliderLeft, mVolumeSliderRight;

	AudioManager mAudioManager;

	private static final int RESULT_ALBUMART_DOWNLOADED = 1;

	// for lyrics displaying
	private TextScrollView mLyricsScrollView;

	private LinearLayout mLyricsView, mInfoView, mVolumeSlider;

	private FrameLayout mVisualizerView;
	private VisualizerWrapper mVisualizer;
	private VisualizerViewWaveForm mVisualizerViewWaveForm;
	private VisualizerViewFftSpectrum mVisualizerViewFftSpectrum;

	private boolean mDisplayLyrics = true;
	private boolean mDisplayVisualizer = false;
	private boolean mShowFadeAnimation = false;
	private boolean mLyricsWakelock = DEFAULT_LYRICS_WAKELOCK;

	private String mTrackName, mArtistName, mAlbumName;

	public MusicPlaybackActivity() {
	}

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);

		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.nowplaying_default);

		mGestureDetector = new GestureDetector(getApplicationContext(),
				mVolumeSlideListener);

		mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

		mVolumeSlider = (LinearLayout) findViewById(R.id.volume_layout);

		mVolumeSliderLeft = findViewById(R.id.volume_slider_left);
		mVolumeSliderLeft.setOnTouchListener(this);

		mVolumeSliderRight = findViewById(R.id.volume_slider_right);
		mVolumeSliderRight.setOnTouchListener(this);

		mLyricsView = (LinearLayout) findViewById(R.id.lyrics_view);

		mLyricsScrollView = (TextScrollView) findViewById(R.id.lyrics_scroll);
		mLyricsScrollView.setContentGravity(Gravity.CENTER_HORIZONTAL);

		mInfoView = (LinearLayout) findViewById(R.id.info_view);

		mVisualizerView = (FrameLayout) findViewById(R.id.visualizer_view);
		mVisualizerViewFftSpectrum = new VisualizerViewFftSpectrum(this);
		mVisualizerViewWaveForm = new VisualizerViewWaveForm(this);

		mCurrentTime = (TextView) findViewById(R.id.currenttime);
		((View) mCurrentTime.getParent())
				.setOnLongClickListener(mToggleVisualizerListener);
		mTotalTime = (TextView) findViewById(R.id.totaltime);
		((View) mTotalTime.getParent())
				.setOnLongClickListener(mToggleVisualizerListener);
		mProgress = (ProgressBar) findViewById(android.R.id.progress);
		mAlbumArt = (ImageView) findViewById(R.id.album);
		mArtistNameView = (TextView) findViewById(R.id.artistname);
		mAlbumNameView = (TextView) findViewById(R.id.albumname);
		mTrackNameButton = (Button) findViewById(R.id.trackname);
		mTrackNameButton.setOnLongClickListener(mTrackNameSearchListener);

		findViewById(R.id.message)
				.setOnLongClickListener(mSearchLyricsListener);

		View v = (View) mLyricsView.getParent();
		v.setOnClickListener(mLyricsClickListener);
		v.setOnLongClickListener(mSearchLyricsListener);

		mPrevButton = (RepeatingImageButton) findViewById(R.id.prev);
		mPrevButton.setOnClickListener(mPrevListener);
		mPrevButton.setRepeatListener(mRewListener, 260);
		mPauseButton = (ImageButton) findViewById(R.id.pause);
		mPauseButton.requestFocus();
		mPauseButton.setOnClickListener(mPauseListener);
		mNextButton = (RepeatingImageButton) findViewById(R.id.next);
		mNextButton.setOnClickListener(mNextListener);
		mNextButton.setRepeatListener(mFfwdListener, 260);

		mDeviceHasDpad = (getResources().getConfiguration().navigation == Configuration.NAVIGATION_DPAD);

		mQueueButton = (ImageButton) findViewById(R.id.curplaylist);
		mQueueButton.setOnClickListener(mQueueListener);
		mQueueButton.setOnLongClickListener(mSearchAlbumArtListener);
		mShuffleButton = (ImageButton) findViewById(R.id.shuffle);
		mShuffleButton.setOnClickListener(mShuffleListener);
		mRepeatButton = (ImageButton) findViewById(R.id.repeat);
		mRepeatButton.setOnClickListener(mRepeatListener);

		mShuffleButton.setBackgroundDrawable(new ButtonStateDrawable(
				new Drawable[] { getResources().getDrawable(
						R.drawable.button_bg) }));
		mTrackNameButton.setBackgroundDrawable(new ButtonStateDrawable(
				new Drawable[] { getResources().getDrawable(
						R.drawable.button_bg) }));
		mRepeatButton.setBackgroundDrawable(new ButtonStateDrawable(
				new Drawable[] { getResources().getDrawable(
						R.drawable.button_bg) }));

		mPrevButton.setBackgroundDrawable(new ButtonStateDrawable(
				new Drawable[] { getResources().getDrawable(
						R.drawable.button_bg) }));
		mPauseButton.setBackgroundDrawable(new ButtonStateDrawable(
				new Drawable[] { getResources().getDrawable(
						R.drawable.button_bg) }));
		mNextButton.setBackgroundDrawable(new ButtonStateDrawable(
				new Drawable[] { getResources().getDrawable(
						R.drawable.button_bg) }));

		if (mProgress instanceof SeekBar) {
			SeekBar seeker = (SeekBar) mProgress;
			seeker.setOnSeekBarChangeListener(mSeekListener);
		}
		mProgress.setMax(1000);
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		int action = event.getAction();
		if (action == MotionEvent.ACTION_DOWN) {
			v.setBackgroundColor(Color.argb(0x33, Color.red(mUIColor),
					Color.green(mUIColor), Color.blue(mUIColor)));
		} else if (action == MotionEvent.ACTION_UP
				|| action == MotionEvent.ACTION_CANCEL) {
			v.setBackgroundColor(Color.TRANSPARENT);
		}
		mGestureDetector.onTouchEvent(event);
		return true;
	}

	@Override
	public void onLineSelected(int id) {
		try {
			mService.seek(mService.getPositionByLyricsId(id));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private OnGestureListener mVolumeSlideListener = new OnGestureListener() {

		int view_height = 0;
		int max_volume = 0;
		float delta = 0;

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			// nothing to do here.
			return false;
		}

		@Override
		public void onShowPress(MotionEvent e) {
		}

		@Override
		public boolean onScroll(MotionEvent event1, MotionEvent event2,
				float distanceX, float distanceY) {
			if (delta >= 1 || delta <= -1) {
				adjustVolume((int) delta);
				delta = 0;
			} else {
				delta += max_volume * distanceY / view_height * 2;
			}
			return false;
		}

		@Override
		public void onLongPress(MotionEvent e) {
			delta = 0;
		}

		@Override
		public boolean onDown(MotionEvent e) {
			max_volume = mAudioManager
					.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
			view_height = mVolumeSlider.getHeight();
			delta = 0;
			return false;
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			return false;
		}
	};

	private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
		public void onStartTrackingTouch(SeekBar bar) {
			mLastSeekEventTime = 0;
			mFromTouch = true;
		}

		public void onProgressChanged(SeekBar bar, int progress,
				boolean fromuser) {
			if (!fromuser || (mService == null))
				return;
			long now = SystemClock.elapsedRealtime();
			if ((now - mLastSeekEventTime) > 250) {
				mLastSeekEventTime = now;
				mPosOverride = mDuration * progress / 1000;
				try {
					mService.seek(mPosOverride);
				} catch (RemoteException ex) {
				}

				// trackball event, allow progress updates
				if (!mFromTouch) {
					refreshNow();
					mPosOverride = -1;
				}
			}
		}

		public void onStopTrackingTouch(SeekBar bar) {
			mPosOverride = -1;
			mFromTouch = false;
		}
	};

	private View.OnClickListener mQueueListener = new View.OnClickListener() {
		public void onClick(View v) {
			startActivity(new Intent(Intent.ACTION_EDIT).setClass(
					MusicPlaybackActivity.this, TrackTabActivity.class)
					.putExtra("playlist", "nowplaying"));
		}
	};

	private View.OnClickListener mShuffleListener = new View.OnClickListener() {
		public void onClick(View v) {
			toggleShuffle();
		}
	};

	private View.OnClickListener mRepeatListener = new View.OnClickListener() {
		public void onClick(View v) {
			toggleRepeat();
		}
	};

	private View.OnClickListener mLyricsClickListener = new View.OnClickListener() {
		public void onClick(View v) {
			toggleLyrics();
		}
	};

	private View.OnLongClickListener mTrackNameSearchListener = new View.OnLongClickListener() {
		public boolean onLongClick(View v) {
			String track = mTrackNameButton.getText().toString();
			String artist = mArtistNameView.getText().toString();
			String album = mAlbumNameView.getText().toString();
			
			CharSequence title = getString(R.string.mediasearch, track);
			Intent i = new Intent();
			i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			i.setAction(MediaStore.INTENT_ACTION_MEDIA_SEARCH);
			i.putExtra(MediaStore.EXTRA_MEDIA_TITLE, track);

			String query = track;
			if (!getString(R.string.unknown_artist_name).equals(artist) && !getString(R.string.unknown_album_name).equals(album)) {
				query = artist + " " + track;
				i.putExtra(MediaStore.EXTRA_MEDIA_ALBUM, album);
				i.putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist);
			} else	if (getString(R.string.unknown_artist_name).equals(artist) && !getString(R.string.unknown_album_name).equals(album)) {
				query = album + " " + track;
				i.putExtra(MediaStore.EXTRA_MEDIA_ALBUM, album);
			} else if (!getString(R.string.unknown_artist_name).equals(artist) && getString(R.string.unknown_album_name).equals(album)){
				query = artist + " " + track;
				i.putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist);
			}
			i.putExtra(SearchManager.QUERY, query);
			i.putExtra(MediaStore.EXTRA_MEDIA_FOCUS, "audio/*");
			startActivity(Intent.createChooser(i, title));
			return true;
		}
	};

	private View.OnLongClickListener mToggleVisualizerListener = new View.OnLongClickListener() {
		public boolean onLongClick(View v) {
			toggleVisualizer();
			return true;
		}
	};

	private View.OnLongClickListener mSearchLyricsListener = new View.OnLongClickListener() {
		public boolean onLongClick(View v) {
			searchLyrics();
			return true;
		}
	};

	private View.OnLongClickListener mSearchAlbumArtListener = new View.OnLongClickListener() {
		public boolean onLongClick(View v) {
			searchAlbumArt();
			return true;
		}
	};

	private View.OnClickListener mPauseListener = new View.OnClickListener() {
		public void onClick(View v) {
			doPauseResume();
		}
	};

	private View.OnClickListener mPrevListener = new View.OnClickListener() {
		public void onClick(View v) {

			if (mService == null)
				return;
			try {
				if (mService.position() < 2000) {
					mService.prev();
				} else {
					mService.seek(0);
					mService.play();
				}
			} catch (RemoteException ex) {
			}
		}
	};

	private View.OnClickListener mNextListener = new View.OnClickListener() {
		public void onClick(View v) {

			if (mService == null)
				return;
			try {
				mService.next();
			} catch (RemoteException ex) {
			}
		}
	};

	private RepeatingImageButton.RepeatListener mRewListener = new RepeatingImageButton.RepeatListener() {
		public void onRepeat(View v, long howlong, int repcnt) {
			scanBackward(repcnt, howlong);
		}
	};

	private RepeatingImageButton.RepeatListener mFfwdListener = new RepeatingImageButton.RepeatListener() {
		public void onRepeat(View v, long howlong, int repcnt) {
			scanForward(repcnt, howlong);
		}
	};

	@Override
	public void onStop() {
		paused = true;

		if (!mIntentDeRegistered) {
			mHandler.removeMessages(REFRESH);
			unregisterReceiver(mStatusListener);
		}

		mLyricsScrollView.unregisterLineSelectedListener(this);
		unregisterReceiver(mScreenTimeoutListener);

		if (mVisualizer != null) {
			mVisualizer.release();
		}

		MusicUtils.unbindFromService(mToken);
		mService = null;

		getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		super.onStop();
	}

	@Override
	public void onStart() {
		super.onStart();
		paused = false;

		setVolumeControlStream(AudioManager.STREAM_MUSIC);

		mToken = MusicUtils.bindToService(this, osc);
		if (mToken == null) {
			// something went wrong
			mHandler.sendEmptyMessage(QUIT);
		}
		IntentFilter f = new IntentFilter();
		f.addAction(BROADCAST_PLAYSTATE_CHANGED);
		f.addAction(BROADCAST_META_CHANGED);
		f.addAction(BROADCAST_NEW_LYRICS_LOADED);
		f.addAction(BROADCAST_LYRICS_REFRESHED);
		f.addAction(BROADCAST_PLAYBACK_COMPLETE);
		f.addAction(BROADCAST_REFRESH_PROGRESSBAR);
		registerReceiver(mStatusListener, new IntentFilter(f));

		IntentFilter s = new IntentFilter();
		s.addAction(Intent.ACTION_SCREEN_ON);
		s.addAction(Intent.ACTION_SCREEN_OFF);
		registerReceiver(mScreenTimeoutListener, new IntentFilter(s));

		mLyricsScrollView.registerLineSelectedListener(this);

		mLyricsWakelock = SharedPrefsUtils.getBooleanPreference(
				MusicPlaybackActivity.this, KEY_LYRICS_WAKELOCK,
				DEFAULT_LYRICS_WAKELOCK);
		mDisplayLyrics = SharedPrefsUtils.getBooleanState(this,
				KEY_DISPLAY_LYRICS, DEFAULT_DISPLAY_LYRICS);
		mAutoColor = SharedPrefsUtils.getBooleanPreference(this,
				KEY_AUTO_COLOR, true);
		mBlurBackground = SharedPrefsUtils.getBooleanPreference(this,
				KEY_BLUR_BACKGROUND, false);

		if (mBlurBackground) {
			getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
		} else {
			getWindow().clearFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
		}

		// show lyrics
		if (mDisplayLyrics) {
			displayLyrics(mShowFadeAnimation, false);
		} else {
			displayInfo(mShowFadeAnimation, false);
		}

		try {
			float mWindowAnimation = Settings.System.getFloat(
					this.getContentResolver(),
					Settings.System.WINDOW_ANIMATION_SCALE);
			float mTransitionAnimation = Settings.System.getFloat(
					this.getContentResolver(),
					Settings.System.TRANSITION_ANIMATION_SCALE);
			if (mTransitionAnimation > 0.0) {
				mShowFadeAnimation = true;
			} else {
				mShowFadeAnimation = false;
			}

			mLyricsScrollView.setSmoothScrollingEnabled(mWindowAnimation > 0.0);

		} catch (SettingNotFoundException e) {
			e.printStackTrace();
		}

		updateTrackInfo();
		long next = refreshNow();
		queueNextRefresh(next);

	}

	@Override
	public void onResume() {
		super.onResume();

		updateTrackInfo();

		if (mIntentDeRegistered) {
			paused = false;
		}
		setPauseButtonImage();
		try {
			if (mService != null && mService.isPlaying() && mDisplayVisualizer) {
				enableVisualizer();
			} else {
				disableVisualizer(false);
			}
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		MenuInflater mInflater = getMenuInflater();
		mInflater.inflate(R.menu.options_menu_playback, menu);

		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		if (mService == null)
			return false;
		MenuItem item = menu.findItem(PARTY_SHUFFLE);
		if (item != null) {
			int shuffle = MusicUtils.getCurrentShuffleMode();
			if (shuffle == SHUFFLE_AUTO) {
				item.setIcon(R.drawable.ic_menu_party_shuffle);
				item.setTitle(R.string.party_shuffle_off);
			} else {
				item.setIcon(R.drawable.ic_menu_party_shuffle);
				item.setTitle(R.string.party_shuffle);
			}
		}

		KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
		menu.setGroupVisible(1, !km.inKeyguardRestrictedInputMode());

		return true;
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode,
			Intent intent) {
		if (resultCode != RESULT_OK) {
			return;
		}
		switch (requestCode) {
		case NEW_PLAYLIST:
			if (resultCode == RESULT_OK) {
				Uri uri = intent.getData();
				if (uri != null) {
					long[] list = new long[1];
					list[0] = MusicUtils.getCurrentAudioId();
					int playlist = Integer.parseInt(uri.getLastPathSegment());
					MusicUtils.addToPlaylist(this, list, playlist);
				}
			}
			break;
		case DELETE_ITEMS:
			if (resultCode == RESULT_DELETE_MUSIC) {
				finish();
			}
			break;
		}
	}

	@Override
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		try {
			switch (keyCode) {
			case KeyEvent.KEYCODE_DPAD_LEFT:
				if (!useDpadMusicControl()) {
					break;
				}
				if (mService != null) {
					if (!mSeeking && mStartSeekPos >= 0) {
						mPauseButton.requestFocus();
						if (mStartSeekPos < 1000) {
							mService.prev();
						} else {
							mService.seek(0);
						}
					} else {
						scanBackward(-1,
								event.getEventTime() - event.getDownTime());
						mPauseButton.requestFocus();
						mStartSeekPos = -1;
					}
				}
				mSeeking = false;
				mPosOverride = -1;
				return true;
			case KeyEvent.KEYCODE_DPAD_RIGHT:
				if (!useDpadMusicControl()) {
					break;
				}
				if (mService != null) {
					if (!mSeeking && mStartSeekPos >= 0) {
						mPauseButton.requestFocus();
						mService.next();
					} else {
						scanForward(-1,
								event.getEventTime() - event.getDownTime());
						mPauseButton.requestFocus();
						mStartSeekPos = -1;
					}
				}
				mSeeking = false;
				mPosOverride = -1;
				return true;
			}
		} catch (RemoteException ex) {
		}
		return super.onKeyUp(keyCode, event);
	}

	private boolean useDpadMusicControl() {
		if (mDeviceHasDpad
				&& (mPrevButton.isFocused() || mNextButton.isFocused() || mPauseButton
						.isFocused())) {
			return true;
		}
		return false;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		int repcnt = event.getRepeatCount();

		switch (keyCode) {

		case KeyEvent.KEYCODE_DPAD_LEFT:
			if (!useDpadMusicControl()) {
				break;
			}
			if (!mPrevButton.hasFocus()) {
				mPrevButton.requestFocus();
			}
			scanBackward(repcnt, event.getEventTime() - event.getDownTime());
			return true;
		case KeyEvent.KEYCODE_DPAD_RIGHT:
			if (!useDpadMusicControl()) {
				break;
			}
			if (!mNextButton.hasFocus()) {
				mNextButton.requestFocus();
			}
			scanForward(repcnt, event.getEventTime() - event.getDownTime());
			return true;

		case KeyEvent.KEYCODE_R:
			toggleRepeat();
			return true;

		case KeyEvent.KEYCODE_S:
			toggleShuffle();
			return true;

		case KeyEvent.KEYCODE_L:
			toggleLyrics();
			return true;

		case KeyEvent.KEYCODE_N:
			if (mService != null) {
				try {
					mService.next();
					return true;
				} catch (RemoteException ex) {
					// ex.printStackTrace();
				}
			} else {
				return false;
			}

		case KeyEvent.KEYCODE_P:
			if (mService != null) {
				try {
					mService.prev();
					return true;
				} catch (RemoteException ex) {
					// ex.printStackTrace();
				}
			} else {
				return false;
			}

		case KeyEvent.KEYCODE_DPAD_CENTER:
			doPauseResume();
			return true;

		case KeyEvent.KEYCODE_SPACE:
			doPauseResume();
			return true;

			// case KeyEvent.KEYCODE_MENU:
			// mQuickAction.show(mMenuButton);
			// return true;
		}

		return super.onKeyDown(keyCode, event);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		Intent intent;
		switch (item.getItemId()) {
		case PARTY_SHUFFLE:
			MusicUtils.togglePartyShuffle();
			setShuffleButtonImage();
			break;
		case ADD_TO_PLAYLIST:
			intent = new Intent(INTENT_ADD_TO_PLAYLIST);
			long[] list_to_be_added = new long[1];
			list_to_be_added[0] = MusicUtils.getCurrentAudioId();
			intent.putExtra(KEY_LIST, list_to_be_added);
			startActivity(intent);
			break;
		case EQUALIZER:
			intent = new Intent(INTENT_EQUALIZER);
			startActivity(intent);
			break;
		case SLEEP_TIMER:
			intent = new Intent(INTENT_SLEEP_TIMER);
			startActivity(intent);
			break;
		case DELETE_ITEMS:
			final long[] list = new long[1];
			list[0] = (int) MusicUtils.getCurrentAudioId();
			intent = new Intent(INTENT_DELETE_ITEMS);
			intent.putExtra(KEY_CONTENT, mTrackName);
			intent.putExtra(KEY_TYPE, TYPE_TRACK);
			intent.putExtra(KEY_ITEMS, list);
			startActivityForResult(intent, DELETE_ITEMS);
			break;
		case SETTINGS:
			intent = new Intent(INTENT_APPEARANCE_CONFIG);
			startActivity(intent);
			break;
		}

		return super.onOptionsItemSelected(item);
	}

	private void scanBackward(int repcnt, long delta) {
		if (mService == null)
			return;
		try {
			if (repcnt == 0) {
				mStartSeekPos = mService.position();
				mLastSeekEventTime = 0;
				mSeeking = false;
			} else {
				mSeeking = true;
				if (delta < 5000) {
					// seek at 10x speed for the first 5 seconds
					delta = delta * 10;
				} else {
					// seek at 40x after that
					delta = 50000 + (delta - 5000) * 40;
				}
				long newpos = mStartSeekPos - delta;
				if (newpos < 0) {
					// move to previous track
					mService.prev();
					long duration = mService.duration();
					mStartSeekPos += duration;
					newpos += duration;
				}
				if (((delta - mLastSeekEventTime) > 250) || repcnt < 0) {
					mService.seek(newpos);
					mLastSeekEventTime = delta;
				}
				if (repcnt >= 0) {
					mPosOverride = newpos;
				} else {
					mPosOverride = -1;
				}
				refreshNow();
			}
		} catch (RemoteException ex) {
		}
	}

	private void scanForward(int repcnt, long delta) {
		if (mService == null)
			return;
		try {
			if (repcnt == 0) {
				mStartSeekPos = mService.position();
				mLastSeekEventTime = 0;
				mSeeking = false;
			} else {
				mSeeking = true;
				if (delta < 5000) {
					// seek at 10x speed for the first 5 seconds
					delta = delta * 10;
				} else {
					// seek at 40x after that
					delta = 50000 + (delta - 5000) * 40;
				}
				long newpos = mStartSeekPos + delta;
				long duration = mService.duration();
				if (newpos >= duration) {
					// move to next track
					mService.next();
					mStartSeekPos -= duration; // is OK to go negative
					newpos -= duration;
				}
				if (((delta - mLastSeekEventTime) > 250) || repcnt < 0) {
					mService.seek(newpos);
					mLastSeekEventTime = delta;
				}
				if (repcnt >= 0) {
					mPosOverride = newpos;
				} else {
					mPosOverride = -1;
				}
				refreshNow();
			}
		} catch (RemoteException ex) {
		}
	}

	private void doPauseResume() {
		try {
			if (mService != null) {
				if (mService.isPlaying()) {
					mService.pause();
				} else {
					mService.play();
				}
				refreshNow();
				setPauseButtonImage();
				setVisualizerView();
			}
		} catch (RemoteException ex) {
		}
	}

	private void toggleShuffle() {
		if (mService == null) {
			return;
		}
		try {
			int shuffle = mService.getShuffleMode();
			if (shuffle == SHUFFLE_NONE) {
				mService.setShuffleMode(SHUFFLE_NORMAL);
				if (mService.getRepeatMode() == REPEAT_CURRENT) {
					mService.setRepeatMode(REPEAT_ALL);
					setRepeatButtonImage();
				}
				showToast(R.string.shuffle_on_notif);
			} else if (shuffle == SHUFFLE_NORMAL || shuffle == SHUFFLE_AUTO) {
				mService.setShuffleMode(SHUFFLE_NONE);
				showToast(R.string.shuffle_off_notif);
			} else {
				Log.e("MusicPlaybackActivity", "Invalid shuffle mode: "
						+ shuffle);
			}
			setShuffleButtonImage();
		} catch (RemoteException ex) {
		}
	}

	private void toggleRepeat() {
		if (mService == null) {
			return;
		}
		try {
			int mode = mService.getRepeatMode();
			if (mode == REPEAT_NONE) {
				mService.setRepeatMode(REPEAT_ALL);
				showToast(R.string.repeat_all_notif);
			} else if (mode == REPEAT_ALL) {
				mService.setRepeatMode(REPEAT_CURRENT);
				if (mService.getShuffleMode() != SHUFFLE_NONE) {
					mService.setShuffleMode(SHUFFLE_NONE);
					setShuffleButtonImage();
				}
				showToast(R.string.repeat_current_notif);
			} else {
				mService.setRepeatMode(REPEAT_NONE);
				showToast(R.string.repeat_off_notif);
			}
			setRepeatButtonImage();
		} catch (RemoteException ex) {
		}

	}

	private void toggleLyrics() {
		if (mDisplayLyrics) {
			displayInfo(mShowFadeAnimation, true);
			mDisplayLyrics = false;
		} else {
			displayLyrics(mShowFadeAnimation, true);
			mDisplayLyrics = true;
		}
		SharedPrefsUtils.setBooleanState(this, KEY_DISPLAY_LYRICS,
				mDisplayLyrics);
	}

	private void toggleVisualizer() {

		boolean isPlaying = false;
		if (mService != null) {
			try {
				isPlaying = mService.isPlaying();
			} catch (Exception e) {
				// nothing to do here
			}
		}

		if (isPlaying) {
			if (mDisplayVisualizer) {
				disableVisualizer(true);
				mDisplayVisualizer = false;
			} else {
				enableVisualizer();
				mDisplayVisualizer = true;
			}
			SharedPrefsUtils.setBooleanState(this, KEY_DISPLAY_VISUALIZER,
					mDisplayVisualizer);
		}
	}

	private void showToast(int resid) {
		if (mToast == null) {
			mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
		}
		mToast.setText(resid);
		mToast.show();
	}

	private void startPlayback() {
		if (mService == null)
			return;
		updateTrackInfo();
		long next = refreshNow();
		queueNextRefresh(next);
	}

	private void displayLyrics(boolean show_animation, boolean fromuser) {

		if (mLyricsWakelock) {
			getWindow()
					.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		}

		if (mInfoView.getVisibility() != View.INVISIBLE) {

			mInfoView.setVisibility(View.INVISIBLE);
			mInfoView.startAnimation(AnimationUtils.loadAnimation(this,
					android.R.anim.fade_out));
		}

		if (mLyricsView.getVisibility() != View.VISIBLE) {

			mLyricsView.setVisibility(View.VISIBLE);
			mLyricsView.startAnimation(AnimationUtils.loadAnimation(this,
					android.R.anim.fade_in));

		}

	}

	private void displayInfo(boolean show_animation, boolean fromuser) {
		getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		if (mInfoView.getVisibility() != View.VISIBLE) {

			mInfoView.setVisibility(View.VISIBLE);
			mInfoView.startAnimation(AnimationUtils.loadAnimation(this,
					android.R.anim.fade_in));
		}

		if (mLyricsView.getVisibility() != View.INVISIBLE) {

			mLyricsView.setVisibility(View.INVISIBLE);
			mLyricsView.startAnimation(AnimationUtils.loadAnimation(this,
					android.R.anim.fade_out));

		}
	}

	private void searchLyrics() {

		String artistName = "";
		String trackName = "";
		String mediaPath = "";
		String lyricsPath = "";
		try {
			artistName = mService.getArtistName();
			trackName = mService.getTrackName();
			mediaPath = mService.getMediaPath();
			lyricsPath = mediaPath.substring(0, mediaPath.lastIndexOf("."))
					+ ".lrc";
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			Intent intent = new Intent(INTENT_SEARCH_LYRICS);
			intent.putExtra(KEY_ARTIST, artistName);
			intent.putExtra(KEY_TRACK, trackName);
			intent.putExtra(KEY_PATH, lyricsPath);
			startActivity(intent);
		} catch (ActivityNotFoundException e) {
			// e.printStackTrace();
		}
	}

	private void searchAlbumArt() {

		String artistName = "";
		String albumName = "";
		String mediaPath = "";
		String albumArtPath = "";
		try {
			artistName = mService.getArtistName();
			albumName = mService.getAlbumName();
			mediaPath = mService.getMediaPath();
			albumArtPath = mediaPath.substring(0, mediaPath.lastIndexOf("/"))
					+ "/AlbumArt.jpg";
		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			Intent intent = new Intent(INTENT_SEARCH_ALBUMART);
			intent.putExtra(KEY_ARTIST, artistName);
			intent.putExtra(KEY_ALBUM, albumName);
			intent.putExtra(KEY_PATH, albumArtPath);
			startActivityForResult(intent, RESULT_ALBUMART_DOWNLOADED);
		} catch (ActivityNotFoundException e) {
			// e.printStackTrace();
		}

	}

	private void loadLyricsToView() {
		try {
			mLyricsScrollView.setTextContent(mService.getLyrics(),
					MusicPlaybackActivity.this);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

	private void scrollLyrics(int lyrics_id, boolean force) {
		mLyricsScrollView.setCurrentLine(lyrics_id, force);
	}

	private void enableVisualizer() {
		if (mVisualizer != null) {
			if (!mVisualizer.getEnabled()
					|| mVisualizerView.getVisibility() != View.VISIBLE) {
				mVisualizerView.setVisibility(View.VISIBLE);
				mVisualizerHandler.sendEmptyMessage(ENABLE_VISUALIZER);
				if (mShowFadeAnimation) {
					mVisualizerView.startAnimation(AnimationUtils
							.loadAnimation(this, android.R.anim.fade_in));
				}
			}
		}
	}

	private void disableVisualizer(boolean animation) {
		if (mVisualizer != null) {
			if (mVisualizer.getEnabled()
					|| mVisualizerView.getVisibility() == View.VISIBLE) {
				mVisualizerView.setVisibility(View.INVISIBLE);
				if (mShowFadeAnimation) {
					mVisualizerView.startAnimation(AnimationUtils
							.loadAnimation(this, android.R.anim.fade_out));
				}
				if (animation) {
					mVisualizerHandler.sendEmptyMessageDelayed(
							DISABLE_VISUALIZER,
							AnimationUtils.loadAnimation(this,
									android.R.anim.fade_out).getDuration());
				} else {
					mVisualizerHandler.sendEmptyMessage(DISABLE_VISUALIZER);
				}

			}
		}

	}

	private final static int DISABLE_VISUALIZER = 0;
	private final static int ENABLE_VISUALIZER = 1;

	Handler mVisualizerHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case DISABLE_VISUALIZER:
				mVisualizer.setEnabled(false);
				break;
			case ENABLE_VISUALIZER:
				mVisualizer.setEnabled(true);
				break;
			}
		}
	};

	private void adjustVolume(int value) {

		int max_volume = mAudioManager
				.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
		int current_volume = mAudioManager
				.getStreamVolume(AudioManager.STREAM_MUSIC);

		if ((value + current_volume) <= max_volume
				&& (value + current_volume) >= 0) {
			mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, value
					+ current_volume, AudioManager.FLAG_SHOW_UI);
		} else if ((value + current_volume) > max_volume) {
			mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
					max_volume, AudioManager.FLAG_SHOW_UI);
		} else if ((value + current_volume) < 0) {
			mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0,
					AudioManager.FLAG_SHOW_UI);
		}

	}

	private ServiceConnection osc = new ServiceConnection() {
		public void onServiceConnected(ComponentName classname, IBinder obj) {
			mService = IMusicPlaybackService.Stub.asInterface(obj);
			startPlayback();

			int audioSession = 0;
			try {
				audioSession = mService.getAudioSessionId();
			} catch (RemoteException e) {
			}

			mVisualizerView.removeAllViews();
			mVisualizer = new VisualizerWrapper(audioSession);
			if (mVisualizer != null) {
				mDisplayVisualizer = SharedPrefsUtils.getBooleanState(
						MusicPlaybackActivity.this, KEY_DISPLAY_VISUALIZER,
						DEFAULT_DISPLAY_VISUALIZER);
				mVisualizerAntialias = SharedPrefsUtils.getBooleanPreference(
						MusicPlaybackActivity.this, KEY_VISUALIZER_ANTIALIAS,
						DEFAULT_VISUALIZER_ANTIALIAS);
				mVisualizerType = Integer.valueOf(SharedPrefsUtils
						.getStringPreference(MusicPlaybackActivity.this,
								KEY_VISUALIZER_TYPE,
								String.valueOf(DEFAULT_VISUALIZER_TYPE)));
				mVisualizerAccuracy = 48 / Integer.valueOf(SharedPrefsUtils
						.getStringPreference(MusicPlaybackActivity.this,
								KEY_VISUALIZER_ACCURACY,
								String.valueOf(DEFAULT_VISUALIZER_ACCURACY)));
				mVisualizerRefreshRate = VisualizerWrapper
						.getMaxCaptureRate(mVisualizer)
						/ Integer
								.valueOf(SharedPrefsUtils.getStringPreference(
										MusicPlaybackActivity.this,
										KEY_VISUALIZER_REFRESHRATE,
										String.valueOf(DEFAULT_VISUALIZER_REFRESHRATE)));
				switch (mVisualizerType) {
				case VISUALIZER_TYPE_WAVE_FORM:
					mVisualizerViewWaveForm.setAntiAlias(mVisualizerAntialias);
					mVisualizerView.addView(mVisualizerViewWaveForm);
					mVisualizer.setCaptureSize(VisualizerWrapper
							.getCaptureSizeRange(mVisualizer)[1] / 2);
					mVisualizer.setDataCaptureListener(
							new OnDataCaptureListener() {
								public void onWaveFormDataCapture(
										VisualizerWrapper visualizer,
										byte[] bytes, int samplingRate) {
									if (mVisualizerView != null) {
										mVisualizerViewWaveForm
												.updateVisualizer(bytes);
									}
								}

								public void onFftDataCapture(
										VisualizerWrapper visualizer,
										byte[] bytes, int samplingRate) {
								}
							}, mVisualizerRefreshRate, true, false);

					break;
				case VISUALIZER_TYPE_FFT_SPECTRUM:
					mVisualizerViewFftSpectrum
							.setAntiAlias(mVisualizerAntialias);
					mVisualizerViewFftSpectrum
							.setFftSamples(mVisualizerAccuracy);
					mVisualizerView.addView(mVisualizerViewFftSpectrum);
					mVisualizer.setCaptureSize(VisualizerWrapper
							.getCaptureSizeRange(mVisualizer)[0]);
					mVisualizer.setDataCaptureListener(
							new OnDataCaptureListener() {
								public void onWaveFormDataCapture(
										VisualizerWrapper visualizer,
										byte[] bytes, int samplingRate) {
								}

								public void onFftDataCapture(
										VisualizerWrapper visualizer,
										byte[] bytes, int samplingRate) {
									if (mVisualizerView != null) {
										byte[] model = new byte[bytes.length / 2 + 1];
										model[0] = (byte) Math.abs(bytes[1]);
										int j = 1;
										for (int i = 2; i <= mVisualizerAccuracy * 2;) {
											model[j] = (byte) Math.hypot(
													bytes[i], bytes[i + 1]);
											i += 2;
											j++;

										}
										mVisualizerViewFftSpectrum
												.updateVisualizer(model);
									}
								}
							}, mVisualizerRefreshRate, false, true);
					break;
				}
			}

			try {
				// Assume something is playing when the service says it is,
				// but also if the audio ID is valid but the service is paused.
				if (mService.getAudioId() >= 0 || mService.isPlaying()
						|| mService.getPath() != null) {
					// something is playing now, we're done
					mRepeatButton.setVisibility(View.VISIBLE);
					mShuffleButton.setVisibility(View.VISIBLE);
					mQueueButton.setClickable(true);
					mQueueButton.setLongClickable(true);
					setRepeatButtonImage();
					setShuffleButtonImage();
					setPauseButtonImage();
					setVisualizerView();
					loadLyricsToView();
					mService.refreshLyrics();
					return;
				}
			} catch (RemoteException ex) {
			}
			// Service is dead or not playing anything. If we got here as part
			// of a "play this file" Intent, exit. Otherwise go to the Music
			// app start screen.
			if (getIntent().getData() == null) {
				Intent intent = new Intent(Intent.ACTION_MAIN);
				intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				intent.setClass(MusicPlaybackActivity.this,
						MusicBrowserActivity.class);
				startActivity(intent);
			}
			finish();
		}

		public void onServiceDisconnected(ComponentName classname) {
			mService = null;
		}
	};

	private void setRepeatButtonImage() {
		if (mService == null)
			return;
		try {
			switch (mService.getRepeatMode()) {
			case REPEAT_ALL:
				mRepeatButton.setImageResource(R.drawable.repeat_all);
				break;
			case REPEAT_CURRENT:
				mRepeatButton.setImageResource(R.drawable.repeat_once);
				break;
			default:
				mRepeatButton.setImageResource(R.drawable.repeat_off);
				break;
			}
		} catch (RemoteException ex) {
		}
	}

	private void setShuffleButtonImage() {
		if (mService == null)
			return;
		try {
			switch (mService.getShuffleMode()) {
			case SHUFFLE_NONE:
				mShuffleButton.setImageResource(R.drawable.shuffle_off);
				break;
			case SHUFFLE_AUTO:
				mShuffleButton.setImageResource(R.drawable.shuffle_auto);
				break;
			default:
				mShuffleButton.setImageResource(R.drawable.shuffle_on);
				break;
			}
		} catch (RemoteException ex) {
		}
	}

	private void setPauseButtonImage() {
		try {
			if (mService != null && mService.isPlaying()) {
				mPauseButton.setImageResource(R.drawable.btn_playback_ic_pause);
			} else {
				mPauseButton.setImageResource(R.drawable.btn_playback_ic_play);
			}
		} catch (RemoteException ex) {
			// nothing to do here
		}
	}

	private void setVisualizerView() {
		try {
			if (mService != null && mService.isPlaying() && mDisplayVisualizer) {
				enableVisualizer();
			} else {
				disableVisualizer(true);
			}
		} catch (RemoteException ex) {
			// nothing to do here
		}
	}

	private ImageView mAlbumArt;
	private TextView mCurrentTime, mTotalTime, mArtistNameView, mAlbumNameView;
	private Button mTrackNameButton;
	private ProgressBar mProgress;
	private long mPosOverride = -1;
	private boolean mFromTouch = false;
	private long mDuration;
	private boolean paused;

	private static final int REFRESH = 1;
	private static final int QUIT = 2;

	private void queueNextRefresh(long delay) {
		if (!paused) {
			Message msg = mHandler.obtainMessage(REFRESH);
			mHandler.removeMessages(REFRESH);
			mHandler.sendMessageDelayed(msg, delay);
		}
	}

	private long refreshNow() {

		if (mService == null)
			return 500;
		try {
			long pos = mPosOverride < 0 ? mService.position() : mPosOverride;
			long remaining = 1000 - (pos % 1000);
			if ((pos >= 0) && (mDuration > 0)) {
				mCurrentTime.setText(MusicUtils.makeTimeString(this,
						(pos + 500) / 1000));

				if (mService.isPlaying()) {
					mCurrentTime.setVisibility(View.VISIBLE);
				} else {
					// blink the counter
					int vis = mCurrentTime.getVisibility();
					mCurrentTime
							.setVisibility(vis == View.INVISIBLE ? View.VISIBLE
									: View.INVISIBLE);
					remaining = 500;
				}

				mProgress.setProgress((int) (1000 * pos / mDuration));
			} else {
				mCurrentTime.setText("--:--");
				mProgress.setProgress(1000);
			}
			// return the number of milliseconds until the next full second, so
			// the counter can be updated at just the right time
			return remaining;
		} catch (RemoteException ex) {
		}
		return 500;
	}

	final Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {

			case REFRESH:
				long next = refreshNow();
				queueNextRefresh(next);
				break;

			case QUIT:
				// This can be moved back to onCreate once the bug that prevents
				// Dialogs from being started from onCreate/onResume is fixed.
				new AlertDialog.Builder(MusicPlaybackActivity.this)
						.setTitle(R.string.service_start_error)
						.setMessage(R.string.service_start_error_msg)
						.setPositiveButton(android.R.string.ok,
								new DialogInterface.OnClickListener() {
									public void onClick(DialogInterface dialog,
											int whichButton) {
										finish();
									}
								}).setCancelable(false).show();
				break;

			default:
				break;
			}
		}
	};

	private BroadcastReceiver mStatusListener = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (BROADCAST_META_CHANGED.equals(action)) {
				updateTrackInfo();
				setPauseButtonImage();
				setVisualizerView();
				queueNextRefresh(1);
			} else if (BROADCAST_NEW_LYRICS_LOADED.equals(action)) {
				loadLyricsToView();
				scrollLyrics(0, true);
			} else if (BROADCAST_LYRICS_REFRESHED.equals(action)) {
				scrollLyrics(intent.getIntExtra(BROADCAST_KEY_LYRICS_ID, 0),
						false);
			} else if (BROADCAST_PLAYBACK_COMPLETE.equals(action)) {
				setPauseButtonImage();
				setVisualizerView();
			} else if (BROADCAST_PLAYSTATE_CHANGED.equals(action)) {
				setPauseButtonImage();
				setVisualizerView();
			} else if (BROADCAST_REFRESH_PROGRESSBAR.equals(action)) {
				refreshNow();
			}
		}
	};

	private BroadcastReceiver mScreenTimeoutListener = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
				if (mIntentDeRegistered) {
					IntentFilter f = new IntentFilter();
					f.addAction(BROADCAST_PLAYSTATE_CHANGED);
					f.addAction(BROADCAST_META_CHANGED);
					f.addAction(BROADCAST_NEW_LYRICS_LOADED);
					f.addAction(BROADCAST_LYRICS_REFRESHED);
					f.addAction(BROADCAST_PLAYBACK_COMPLETE);
					f.addAction(BROADCAST_REFRESH_PROGRESSBAR);
					registerReceiver(mStatusListener, new IntentFilter(f));
					mIntentDeRegistered = false;
				}

				updateTrackInfo();
				//TODO refresh lyrics
				loadLyricsToView();
				try {
					mService.refreshLyrics();
				} catch (RemoteException e) {
					e.printStackTrace();
				}
				long next = refreshNow();
				queueNextRefresh(next);
			} else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
				paused = true;

				if (!mIntentDeRegistered) {
					mHandler.removeMessages(REFRESH);
					unregisterReceiver(mStatusListener);
					mIntentDeRegistered = true;
				}
			}
		}
	};

	private void updateTrackInfo() {
		if (mService == null) {
			return;
		}
		try {
			String path = mService.getPath();
			if (path == null) {
				finish();
				return;
			}

			mTrackName = mService.getTrackName();
			mArtistName = mService.getArtistName();
			mAlbumName = mService.getAlbumName();

			mArtistNameView.setVisibility(View.VISIBLE);
			mAlbumNameView.setVisibility(View.VISIBLE);
			mTrackNameButton.setText(mTrackName);
			mArtistNameView.setText(mArtistName);
			mAlbumNameView.setText(mAlbumName);
			mAlbumArt.setImageBitmap(mService.getAlbumArt());
			mDuration = mService.duration();
			mTotalTime.setText(MusicUtils
					.makeTimeString(this, mDuration / 1000));

			if (mAutoColor) {
				mUIColor = ColorAnalyser.analyseFromBitmap(mService
						.getAlbumArt());
			} else {
				mUIColor = SharedPrefsUtils.getIntPreference(
						MusicPlaybackActivity.this, KEY_CUSTOMIZED_COLOR,
						Color.WHITE);
			}
			setUIColor(mUIColor);

		} catch (RemoteException ex) {
			finish();
		}
	}

	private void setUIColor(int color) {

		LayerDrawable mLayerDrawableProgress = (LayerDrawable) mProgress
				.getProgressDrawable();
		mLayerDrawableProgress.getDrawable(
				mLayerDrawableProgress.getNumberOfLayers() - 1).setColorFilter(
				mUIColor, Mode.MULTIPLY);
		mProgress.invalidate();

		if (mVisualizerViewWaveForm != null) {
			mVisualizerViewWaveForm.setColor(mUIColor);
		}
		if (mVisualizerViewFftSpectrum != null) {
			mVisualizerViewFftSpectrum.setColor(mUIColor);
		}
	}

	private class ButtonStateDrawable extends LayerDrawable {

		int pressed = android.R.attr.state_pressed;
		int focused = android.R.attr.state_focused;

		public ButtonStateDrawable(Drawable[] layers) {
			super(layers);
		}

		@Override
		protected boolean onStateChange(int[] states) {
			for (int state : states) {
				if (state == pressed || state == focused) {
					super.setColorFilter(mUIColor, Mode.MULTIPLY);
					return super.onStateChange(states);
				}
			}
			super.clearColorFilter();
			return super.onStateChange(states);
		}

		@Override
		public boolean isStateful() {
			return super.isStateful();
		}
	}

}